package com.angel.architecture.syncronization.event;

import java.util.Queue;

import com.angel.architecture.event.base.ApplicationEvent;
import com.angel.architecture.event.base.EventDispatcherImpl;

@SuppressWarnings("unchecked")
public class PropertyChangeEvent extends ApplicationEvent {
    public static final String PROPERTY_CHANGE = "PROPERTY_CHANGE";

    protected Object changedObject;
    protected String propertyName;
    protected Object oldState;
    protected Object newState;

    protected boolean isLastEvent(EventDispatcherImpl eventDispatcher) {
        boolean reachedThis = false;
        Queue<ApplicationEvent> applicationEventQueue = eventDispatcher.getPendingEvents();
        for (ApplicationEvent event : applicationEventQueue) {
            if (event == this) {
                reachedThis = true;
                continue;
            }
            if (event instanceof PropertyChangeEvent) {
                PropertyChangeEvent pce = (PropertyChangeEvent) event;
                if (reachedThis && pce.getChangedObject() == changedObject && pce.getPropertyName().equals(propertyName)) {
                    return false;
                }
            }
        }
        return true;
    }

    public PropertyChangeEvent(Object changedObject, String propertyName, Object oldState, Object newState) {
        super(PROPERTY_CHANGE);
        this.changedObject = changedObject;
        this.propertyName = propertyName;
        this.oldState = oldState;
        this.newState = newState;
    }

    public PropertyChangeEvent(Object eventIdentifier, Object changedObject, String propertyName, Object oldState, Object newState) {
        super(eventIdentifier);
        this.changedObject = changedObject;
        this.propertyName = propertyName;
        this.oldState = oldState;
        this.newState = newState;
    }

    public PropertyChangeEvent() {
    }


    public Object getChangedObject() {
        return changedObject;
    }

    public String getPropertyName() {
        return propertyName;
    }

    public <T> T getOldState() {
        return (T) oldState;
    }

    public <T> T getNewState() {
        return (T) newState;
    }

    @Override
    public boolean beforeDispatch(EventDispatcherImpl eventDispatcher) {
        return isLastEvent(eventDispatcher);
    }
}
